package ar.com.unlp.fi.lrs.service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import ar.com.unlp.fi.lrs.domain.Activity;
import ar.com.unlp.fi.lrs.domain.Actor;
import ar.com.unlp.fi.lrs.domain.Group;
import ar.com.unlp.fi.lrs.domain.Statement;
import ar.com.unlp.fi.lrs.domain.StatementObject;
import ar.com.unlp.fi.lrs.persist.ActivityDao;
import ar.com.unlp.fi.lrs.persist.StatementDao;

@Service
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@Transactional
public class StatementService extends AbstractService {

//	 final static Logger logger = Logger.getLogger(StatementService.class);

	private StatementDao statementDao = new StatementDao();
	
	private ActivityDao activityDao = new ActivityDao();
	
	@Autowired
	private ActorService actorService;
	
	@Autowired
	private VerbService verbService;
	
	@Autowired
	private ContextService contextService;
	
	
	/**
	 * Se crea un statement
	 * 
	 * @param statement
	 */
	public void create(Statement statement) {

		// Si es una actividad se debe persistir.
		if (statement.getObject().getObjectStatemetnType()
				.equals(StatementObject.ACTIVITY)) {

			activityDao.save((Activity) statement.getObject());
		}

		// Se agrega el object, junto a su tipo.
		statement.setObjectType(statement.getObject().getObjectStatemetnType());
		statement.setObjectId(statement.getObject().getId());		
				
		// Se persiste el statemet
		statementDao.save(statement);

		
		
		
		// TODO: push notification a los clientes móviles

	}

	
	
	/**
	 * Se crea un statement y se lo asocia al contexto mediante las extensiones.
	 * 
	 * @param statement
	 */
	public void create(long idStatement, Statement extensionStatement) {

		this.create(extensionStatement);
		
		contextService.addExtension(idStatement, extensionStatement);

	}
	
	/**
	 * Recupera un statement dado junto a todas sus relaciones.
	 * 
	 * @param id
	 * @return
	 */
	public Statement get(long id, long idAgent) {


		Statement statement = statementDao.get(id);
		
		//Se carga la activity si es el caso
		if(StatementObject.ACTIVITY.equals(  statement.getObjectType())){
			
			statement.setObject(activityDao.get(statement.getObjectId()));
		}
		
		//Se crea statement del tipo historial
		createHistory(idAgent, statement);
		
		return statement;
	}

	
	/**
	 * 
	 * Genera la lista de statements para un actor dado.
	 * 
	 * Consideraciones: -Si idGroup es 0 devuelve todos los statments por actor
	 * -Si idActor es 0, entonces devuelve todos los statements
	 * 
	 * 
	 * @param idActor
	 * @param idGroup
	 * @return statements
	 */
	public List<Statement> getAll(long idActor, long idGroup) {

//		Set<Actor> actors = new HashSet<Actor>();
//		List<Group> groups = new ArrayList<Group>();
		List<Statement> statemetns=new ArrayList<Statement>();
		
		
		//Se obtienen el/los grupos del actor
//		if (idGroup == 0) {
//			// Se obtiene todos los grupos del actor.
//			groups = actorService.getGroups(idActor);
//		} else {
//			// Se obtiene el grupo especificado.
//			groups.add( (Group) actorService.get(idGroup));
//		}
//		
//		
//		
//		//Se obtiene todos los actores de los grupos
//		actors.addAll(groups);
//		for (Group group : groups) {
//			actors.addAll(group.getMembers());
//		}
//
//		
//		//Se obtieene todos los statements de los actores
//		for (Actor actores : groups) {
//			
//			statemetns.addAll (statementDao.getAll(actores.getId()));
//		}
		
		
		

		statemetns.addAll(statementDao.getAll());
	
		for (Statement statement : statemetns) {
			//Se carga la activity si es el caso
			if(StatementObject.ACTIVITY.equals(  statement.getObjectType())){
				
				statement.setObject(activityDao.get(statement.getObjectId()));
			}
		}
		
		
		return statemetns;
		
	}
	
	

	/**
	 * Crea un statement historial
	 * 
	 * @param idAgent
	 * @param statement
	 */
	private void createHistory(long idAgent, Statement statement) {
		
		Statement historial=new Statement();
		historial.setActor(actorService.get(idAgent));
		historial.setVerb(verbService.get(3));//3= visto
		historial.setObject(statement);
		
		this.create(historial);
	}

	
}
